package com.asimplefox.service.stand;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.asimplefox.entity.paypal.PayPalAccessToken;
import com.asimplefox.entity.paypal.PayPalOrder;
import com.asimplefox.service.abst.ResultU;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.UUID;

/**
 * @author github.kloping
 */
@Service
@Slf4j
public class PayPalService implements ResultU {
    @Value("${paypal.client-secret}")
    private String secret;
    @Value("${paypal.client-id}")
    private String id;
    public static final RestTemplate REST_TEMPLATE = new RestTemplate();

    public static final String ACCESS_TOKEN_URL = "https://api-m.sandbox.paypal.com/v1/oauth2/token";

    private PayPalAccessToken accessToken = null;

    public String getAccessToken() throws IOException {
        synchronized (this) {
            if (accessToken != null && accessToken.isAccessTokenValid()) {
                return accessToken.getAccess_token();
            }
            String aaa = id + ":" + secret;
            String auth = Base64.getEncoder().encodeToString(aaa.getBytes(StandardCharsets.UTF_8));
            Document doc0 = Jsoup.connect(ACCESS_TOKEN_URL).ignoreContentType(true).ignoreHttpErrors(true)
                    .header("Authorization", "Basic " + auth)
                    .header("Content-Type", "application/x-www-form-urlencoded")
                    .requestBody("grant_type=client_credentials").post();
            String json = doc0.body().text();
            JSONObject jsonObject = JSONObject.parseObject(json);
            PayPalAccessToken response = jsonObject.toJavaObject(PayPalAccessToken.class);
            log.debug("paypal access token:{}", response);
            return (accessToken = response).getAccess_token();
        }
    }

    @Value("${paypal.return-url}")
    private String return_url;

    @Value("${paypal.cancel-url}")
    private String cancel_url;

    public static final String ORDER_URL = "https://api-m.sandbox.paypal.com/v2/checkout/orders";

    public PayPalOrder order(String username, String title, String value) throws IOException {
        JSONObject amount = new JSONObject();
        amount.put("currency_code", "USD");
        amount.put("value", value);
        JSONObject shipping = getShipping(username);
        // 购买人信息，数组，最多可以同时传10个
        JSONObject purchaseUnit = new JSONObject();
        purchaseUnit.put("reference_id", UUID.randomUUID().toString());
        purchaseUnit.put("custom_id", UUID.randomUUID().toString());
        purchaseUnit.put("amount", amount);
        purchaseUnit.put("description", title);
        purchaseUnit.put("shipping", shipping);
        JSONArray puprchase_units = new JSONArray();
        puprchase_units.add(purchaseUnit);
        // 订单上下文信息，取消地址、返回地址设置
        JSONObject applicationContext = new JSONObject();
        applicationContext.put("cancel_url", cancel_url);
        applicationContext.put("return_url", return_url);

        JSONObject json = new JSONObject();
        json.put("intent", "CAPTURE");
        json.put("purchase_units", puprchase_units);
        json.put("application_context", applicationContext);
        String token = getAccessToken();
        Document doc0 = Jsoup.connect(ORDER_URL).ignoreContentType(true).ignoreHttpErrors(true)
                .header("Content-Type", "application/json")
                .header("PayPal-Request-Id", UUID.randomUUID().toString())
                .header("Authorization", "Bearer " + token)
                .requestBody(json.toJSONString())
                .post();
        String data = doc0.body().text();
        PayPalOrder payPalOrder = JSONObject.parseObject(data, PayPalOrder.class);
        log.debug("PayPalOrder created：{}", data);
        return payPalOrder;
    }

    private static JSONObject getShipping(String username) {
        JSONObject address = new JSONObject();
        address.put("admin_area_1", "安徽");
        address.put("admin_area_2", "合肥");
        address.put("address_line_1", "蜀山区");
        address.put("address_line_2", "庐阳区");
        address.put("postal_code", "230000");
        address.put("country_code", "CN");
        // 客户姓名
        JSONObject name = new JSONObject();
        name.put("full_name", username);
        // 客户信息机地址
        JSONObject shipping = new JSONObject();
        shipping.put("name", name);
        shipping.put("address", address);
        return shipping;
    }

    public static String PAY_URL = "https://www.sandbox.paypal.com/checkoutnow?token=";

    //确认
    public JSONObject capture(String pid) throws IOException {
        // 传入订单ID作为路径参数
        String api = String.format("https://api-m.sandbox.paypal.com/v2/checkout/orders/%1s/capture", pid);
        String token = getAccessToken();
        Document doc0 = Jsoup.connect(api).ignoreContentType(true).ignoreHttpErrors(true)
                .header("Content-Type", "application/json")
                .header("PayPal-Request-Id", UUID.randomUUID().toString())
                .header("Authorization", "Bearer " + token)
                .post();
        log.debug("on capture: {}", doc0.body().text());
        return JSONObject.parseObject(doc0.body().text());
    }

    //查询
    public JSONObject query(String pid) throws IOException {
        // 传入订单ID作为路径参数
        String api = String.format("https://api-m.sandbox.paypal.com/v2/checkout/orders/%1s", pid);
        String token = getAccessToken();
        Document doc0 = Jsoup.connect(api).ignoreContentType(true).ignoreHttpErrors(true)
                .header("Content-Type", "application/json")
                .header("PayPal-Request-Id", UUID.randomUUID().toString())
                .header("Authorization", "Bearer " + token)
                .get();
        log.debug("on query: {}", doc0.body().text());
        return JSONObject.parseObject(doc0.body().text());
    }

    //取消
    public JSONObject cancel(String pid) throws IOException {
        // 传入订单ID作为路径参数
        String api = String.format("https://api-m.sandbox.paypal.com/v2/checkout/orders/%1s", pid);
        String token = getAccessToken();
        Document doc0 = Jsoup.connect(api).ignoreContentType(true).ignoreHttpErrors(true)
                .header("Content-Type", "application/json")
                .header("PayPal-Request-Id", UUID.randomUUID().toString())
                .header("Authorization", "Bearer " + token)
                .method(Connection.Method.DELETE).execute().parse();
        log.debug("on cancel: {}", doc0.body().text());
        return JSONObject.parseObject(doc0.body().text());
    }
}
